#include <stdio.h>
#include <stdlib.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include "linklist.h"
#include "comm.h"


//链表，尾部插入，头部取出

int list_add_node(linklist_s *list, void *data, int size)
{
    linknode_s *node;
    void *dt = NULL;

    if((NULL == list) || (NULL == data) ){
        return -1;
    }

    if(list->num >= list->capacity){
        pthread_mutex_lock(&list->mutex);
        node = list->head->next;
        list->head->next = node->next;
        if(node){
            if(node->data){
                free(node->data);
            }
            free(node);
            node = NULL;
        }
        list->num--;
        pthread_mutex_unlock(&list->mutex);
    }

    
    node = (linknode_s *)calloc(1, sizeof(linknode_s));
    if(NULL == node){
        zc_debug("calloc failed");
        return -1;
    }
    
    pthread_mutex_lock(&list->mutex);
    dt = calloc(1, size);
    if (NULL == dt)
    {
        zc_debug("calloc failed");
        free(node);
        pthread_mutex_unlock(&list->mutex);
        return -1;
    }

    memcpy(dt, data, size);

    
    node->next = NULL;
    node->data = dt;
    node->size = size;
    list->tail->next = node;
    list->tail = node;
    list->num ++;
    pthread_mutex_unlock(&list->mutex);

    return 0;
}

int list_pop_node(linklist_s * list, void * data)
{
    linknode_s *node;
    int size = 0;

    if(NULL == list || NULL == data){
        return -1 ;
    }
    
    if(0 == list->num){
        return -1;
    }
    pthread_mutex_lock(&list->mutex);
    node = list->head->next;
    list->head->next = node->next;
    node->next = NULL;
    list->num --;

    if(list->num == 0){
        list->tail = list->head;
        list->head->next = NULL;
    }
    
    
    if(node && node->data){
        size = node->size;
        memcpy(data, node->data, node->size);
        if(list->record){
            list->record(node->data);
        }
        free(node->data);
        free(node);
    }
    pthread_mutex_unlock(&list->mutex);

    return size;
}



linklist_s * list_init(record_fn record, int cap)
{
	linklist_s *list;

    list = (linklist_s *)calloc(1, sizeof(linklist_s));
    if(NULL == list){
        zc_debug("calloc failed");
        return NULL;
    }
    
    list->head = (linknode_s *)calloc(1, sizeof(linknode_s));
    if(NULL == list->head){
        zc_debug("calloc failed");
        free(list);
        return NULL;
    }

    list->capacity = cap;

    list->head->next = NULL;
    list->head->data = NULL;
    list->num = 0;
    list->tail = list->head;
    if(record){
        list->record = record;
    }else{
        list->record = NULL;
    }
    

    pthread_mutex_init(&list->mutex, NULL);

    return list;
}


void list_clear(linklist_s *list)
{
    linknode_s *node;
    void *data;
    if((NULL == list) || (list->head == list->tail)){
        //list is empty
        return ;
    }

    data = calloc(1, 4096);
    if(!data){
        return;
    }

    while(list->num){
        list_pop_node(list, data);
    }
    free(data);

}

void list_del(linklist_s * list)
{
    if(!list){
        return ;
    }
    
    list_clear(list);
    if(list->head){
        free(list->head);
    }
    free(list);
    zc_debug("list is delete");
    return ;
}

